
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

/**
 * 统计代码行数
 */
public class CalcCodeRows {

	static long classcount = 0; // 文件的数量
	static long normalLines = 0; // 空行数量
	static long commentLines = 0; // 注释行数量
	static long writeLines = 0; // 代码行数量
	static long allLines = 0; // 总代码行数量

	public static void main(String[] args) throws Exception {
		File f = new File("C:\\workspace_study\\sample\\src\\main"); // 目录
		String type = ".java";// 查找什么类型的代码，如".java"就是查找以java开发的代码量，".php"就是查找以PHP开发的代码量
		type = ".java"; // sql xml
		CalcCodeRows.treeFile(f, type);
		System.out.println("统计代码路径：" + f.getPath());
		System.out.println("统计代码文件类型：" + type);
		System.out.println(type + "文件数量：" + classcount);
		System.out.println(type + "代码总行数：" + allLines);
		System.out.println(type + "代码实际行数：" + writeLines);
		System.out.println(type + "代码注释行数：" + commentLines);
		System.out.println(type + "代码空行数：" + normalLines);
		if (classcount == 0) {
			System.out.println(type + "代码文件平均行数:" + 0);
		} else {
			System.out.println(type + "代码文件平均行数:" + writeLines / classcount);
		}
	}

	/**
	 * 查找出一个目录下所有的.java文件
	 * @param f
	 * @param type
	 * @throws Exception
	 */
	public static void treeFile(File f, String type) throws Exception {
		File[] childs = f.listFiles();
		for (int i = 0; i < childs.length; i++) {
			File file = childs[i];
			if (!file.isDirectory()) {
				if (file.getName().endsWith(type)) {
					classcount++;
					BufferedReader br = null;
					boolean comment = false;
					br = new BufferedReader(new FileReader(file));
					String line = "";
					while ((line = br.readLine()) != null) {
						allLines++;
						line = line.trim();
						if (line.matches("^[//s&&[^//n]]*$")) {// 这一行匹配以空格开头，但不是以回车符开头，但以回车符结尾
							normalLines++;
						} else if (line.startsWith("/*") && !line.endsWith("*/")) {// 匹配以/*......*/括住的多行注释
							commentLines++;
							comment = true;
						} else if (true == comment) {
							commentLines++;
							if (line.endsWith("*/")) {
								comment = false;
							} // 匹配以//开头的单行注释，及以/*......*/括住的单行注释
						} else if (line.startsWith("//") || (line.startsWith("/*") && line.endsWith("*/"))) {
							commentLines++;
						} else {// 其他的就是代码行
							writeLines++;
						}
					}
					if (br != null) {
						br.close();
						br = null;
					}
				}
			} else {
				treeFile(childs[i], type);
			}
		}
	}

}
